import {NestFactory} from '@nestjs/core';
// 业务路由组件
import {MainModule} from './main.module';
// 错误中间件
import {HttpExceptionFilter} from './common/middleware/error/error.module';
// 验证组件
import {Inject, ValidationPipe, Logger} from "@nestjs/common";
import * as helmet from 'helmet'; // https://github.com/helmetjs/helmet
import * as csrf from 'csurf'; // https://github.com/expressjs/csurf#csurf
import * as rateLimit from 'express-rate-limit';
import * as cookieParser from 'cookie-parser';
import * as bodyParser from "body-parser";
import * as session from "express-session"
import { ConfigService } from "./config/config.service";
// express https://github.com/expressjs

// 应用程序入口文件。它使用 NestFactory 用来创建 Nest 应用实例。
async function bootstrap() {
    // 初始化MainModule
    const app = await NestFactory.create(MainModule,
        {
            // logger: false, // 可以继承LoggerService 自定义自己的组件
            cors: {
                "origin": "*", // 这里可以为array，设置正则或者白名单域名
                "methods": "GET,POST",
                "preflightContinue": false,
                "optionsSuccessStatus": 204
            } // https://github.com/expressjs/cors
        });
    // 设置请求间隔限制组件
    app.use(
        rateLimit({
            windowMs: 2 * 60 * 1000, // 2 minutes
            max: 100, // limit each IP to 100 requests per windowMs 15分钟最多2次
        }),
    );
    // 使用cookie解析器
    app.use(cookieParser());
    // Parse the request body as JSON
    // body解析器
    app.use(bodyParser.json());
    // Parse the URL encoded data
    app.use(bodyParser.urlencoded({extended: true}));
    // Set up session-cookie
    app.use(session({
        secret: "secret",
        resave: false,
        saveUninitialized: true,
        cookie: {
            secure: true,
            httpOnly: true,
            maxAge: 1000 * 60 * 60 * 24
        }
    }));
    // 设置csurf攻击,脚本攻击
    /**
     * 假装用户已经登陆过了，访问其他网站的时候，里面有些这个链接的请求，就会验证通过
     * 服务器向客户端发送令牌。
     客户提交带有令牌的表格。
     如果令牌无效，服务器将拒绝该请求。
     */
    // app.use(csrf({ cookie: true }))
    // 设置http响应头 xssFilter
    app.use(helmet());

    // 加载错误模块,http 错误处理模块，捕捉HttpException
    app.useGlobalFilters(new HttpExceptionFilter());
    // 自动验证，如是否是数字等等
    app.useGlobalPipes(new ValidationPipe({
        transform: true, // 自动有效负载转换，将DTO类自动转成对象
        whitelist: true, // 自动验证自动删除不需要的属性
        disableErrorMessages: false // 详细错误信息
    }));
    let configService = app.get(ConfigService); // 获取配置
    let port = configService.get("PORT");
    Logger.log( `APP start port ${port}`,"main");
    await app.listen(port);
}

bootstrap();
